import {
  Fog,
  Group,
  MeshBasicMaterial,
  DirectionalLight,
  AmbientLight,
  PointLight,
  Vector3,
  LineBasicMaterial,
  Color,
  MeshStandardMaterial,
  PlaneGeometry,
  PointsMaterial,
  Mesh,
  DoubleSide,
  RepeatWrapping,
  SRGBColorSpace,
  AdditiveBlending,
  NearestFilter,
  BoxGeometry,
  SpriteMaterial,
  Sprite,
  MeshLambertMaterial,
} from "three";
import {
  Mini3d,
  Particles,
  FlyLine,
  PathLine,
  Label3d,
  ToastLoading,
  Plane,
  GradientShader,
  getBoundBox,
  createHistory,
} from "@/mini3d";
import testData from "@/assets/test";
import { Assets } from "./map/assets";
import { ExtrudeMap } from "./map/extrudeMap";

import { DiffuseShader } from "./map/DiffuseShader";

import labelArrow from "@/assets/texture/label-arrow.png";

import provincesData from "./map/provincesData";
import scatterData from "./map/scatter";
import badgesData from "./map/badgesData";

import { Reflector } from "./map/Reflector.js";
import { InteractionManager } from "three.interactive";
import { ChildMap } from "./map-china-child";
import gsap from "gsap";
import emitter from "@/utils/emitter";
// 排序
function sortByValue(data) {
  data.sort((a, b) => b.value - a.value);
  return data;
}
// 资源加载
let base_url = import.meta.env.BASE_URL;
export class World extends Mini3d {
  constructor(canvas, config) {
    super(canvas, config);
    this.adcode = "100000";
    // this.adcode = "510000";
    // this.adcode = "110000";

    // 中心坐标
    this.flyLineCenter = [116.41995, 40.18994];
    this.depth = 5;
    // 雾
    this.scene.fog = new Fog(0x102736, 1, 50);
    this.scene.background = new Color(0x102736);
    this.camera.instance.position.set(
      0.00002366776247217723,
      225.1025284992283,
      0.0002238648924037432
    );
    this.camera.instance.near = 1;
    this.camera.instance.far = 10000;
    this.camera.instance.updateProjectionMatrix();
    // 交互管理器
    this.interactionManager = new InteractionManager(
      this.renderer.instance,
      this.camera.instance,
      this.canvas
    );
    this.initSetting();
    this.initEnvironment();
    this.toastLoading = new ToastLoading();
    this.history = new createHistory();
    this.history.push({ name: "中国" });
    this.returnBtn = document.querySelector(".return-btn");
    this.clicked = false; // 是否已经点击
    this.currentScene = "mainScene"; // 当前场景 mainScene | childScene
    this.assets = new Assets(() => {
      // 场景组
      this.sceneGroup = new Group();
      this.mainSceneGroup = new Group();
      this.childSceneGroup = new Group();
      this.labelGroup = new Group();
      this.gqGroup = new Group(); // 光圈组
      this.provinceNameGroup = new Group();
      this.badgeGroup = new Group();
      this.label3d = new Label3d(this);
      this.mainSceneGroup.rotateX(-Math.PI / 2);
      this.areaPointGroup = new Group();
      this.infoLabelGroup = new Group();
      this.areaLabelGroup = new Group();
      this.mainSceneGroup.add(
        this.labelGroup,
        this.gqGroup,
        this.provinceNameGroup,
        this.badgeGroup,
        this.areaPointGroup,
        this.infoLabelGroup,
        this.areaLabelGroup
      );
      this.sceneGroup.add(this.mainSceneGroup, this.childSceneGroup);
      this.scene.add(this.sceneGroup);
      // 创建底图
      this.createFloor();
      // 旋转边框

      this.createRotateBorder();
      // 处理地图
      this.createModel();
      // debugger;
      this.setScale(this.provinceMesh); // 确保先设置缩放和boundBox
      // 添加事件
      this.addEvent();
      // 创建柱状图
      this.createBar();

      // 创建粒子
      this.createParticles();
      // 创建飞线
      this.createFlyLine();
      // 创建散点图
      this.createScatter();
      // 创建标牌
      this.createBadgeLabel();
      // 创建路径动画
      this.createPathAnimate();
      // 创建描边动画
      this.createStorke();
      this.t1Init();
    });
    this.allPointLabel = [];
    this.allInfoLabel = [];
    this.pointEventElement = [];
  }
  t1Init() {
    let tl = gsap.timeline();
    // 相机动画
    tl.addLabel("focusMap", 3.5);
    tl.addLabel("focusMapOpacity", 4.0);
    tl.addLabel("bar", 5.0);
    tl.add(
      gsap.to(this.camera.instance.position, {
        duration: 2.5,
        delay: 2,
        x: 20.134497983573052,
        y: 73.8312346165316,
        z: 120.77649752477839,
        ease: "circ.out",
        onComplete: () => {
          this.camera.controls.saveState();
        },
      })
    );

    tl.add(
      gsap.to(this.quan.rotation, {
        duration: 5,
        z: -2 * Math.PI,
      }),
      "-=2"
    );

    tl.add(
      gsap.to(this.focusMapGroup.position, {
        duration: 1,
        x: 0,
        y: 0,
        z: 0,
      }),
      "focusMap"
    );
    tl.add(
      gsap.to(this.focusMapGroup.scale, {
        duration: 1,
        x: 1,
        y: 1,
        z: 1,
        ease: "circ.out",
      }),
      "focusMap"
    );

    this.provinceMesh.mapGroup.traverse((obj) => {
      if (obj.isMesh) {
        tl.add(
          gsap.to(obj.material[0], {
            duration: 1,
            opacity: 1,
            ease: "circ.out",
          }),
          "focusMapOpacity"
        );
        tl.add(
          gsap.to(obj.position, {
            duration: 1,
            x: 0,
            y: 0,
            z: 0,
            ease: "circ.out",
          }),
          "focusMapOpacity"
        );
      }
    });
    tl.add(
      gsap.to(this.focusMapSideMaterial, {
        duration: 1,
        opacity: 1,
        ease: "circ.out",
        onComplete: () => {
          this.createMirror();
          this.createGridRipple();
        },
      }),
      "focusMapOpacity"
    );

    tl.add(
      gsap.to(this.provinceLineMaterial, {
        duration: 0.5,
        delay: 0.3,
        opacity: 1,
      }),
      "focusMapOpacity"
    );

    tl.add(
      gsap.to(this.rotateBorder1.scale, {
        delay: 0.3,
        duration: 1,
        x: 1,
        y: 1,
        z: 1,
        ease: "circ.out",
      }),
      "focusMapOpacity"
    );
    tl.add(
      gsap.to(this.rotateBorder2.scale, {
        duration: 1,
        delay: 0.5,
        x: 1,
        y: 1,
        z: 1,
        ease: "circ.out",
        onComplete: () => {
          emitter.$emit("mapPlayComplete");
        },
      }),
      "focusMapOpacity"
    );
    this.allBar.map((item, index) => {
      tl.add(
        gsap.to(item.scale, {
          duration: 1,
          delay: 0.05 * index,
          x: 1,
          y: 1,
          z: 1,
          ease: "circ.out",
        }),
        "bar"
      );
    });
    this.allBarMaterial.map((item, index) => {
      tl.add(
        gsap.to(item, {
          duration: 0.5,
          delay: 0.05 * index,
          opacity: 1,
          ease: "circ.out",
        }),
        "bar"
      );
    });
    this.allProvinceLabel.map((item, index) => {
      let element = item.element.querySelector(".provinces-label-style02-wrap");
      let number = item.element.querySelector(".number .value");
      let numberAnimate = {
        score: 0,
      };
      tl.add(
        gsap.to(element, {
          duration: 0.5,
          delay: 0.05 * index,
          translateY: 0,
          opacity: 1,
          ease: "circ.out",
        }),
        "bar"
      );
      let text = gsap.to(numberAnimate, {
        duration: 0.5,
        delay: 0.05 * index,
      });
      function showScore() {
        number.innerText = numberAnimate.score.toFixed(0);
      }
      tl.add(text, "bar");
    });
    this.allProvinceNameLabel.map((item, index) => {
      let element = item.element.querySelector(".provinces-name-label-wrap");
      tl.add(
        gsap.to(element, {
          duration: 0.5,
          delay: 0.05 * index,
          translateY: 0,
          opacity: 1,
          ease: "circ.out",
        }),
        "bar"
      );
    });
    this.allGuangquan.map((item, index) => {
      tl.add(
        gsap.to(item.children[0].scale, {
          duration: 0.5,
          delay: 0.05 * index,
          x: 1,
          y: 1,
          z: 1,
          ease: "circ.out",
        }),
        "bar"
      );
      tl.add(
        gsap.to(item.children[1].scale, {
          duration: 0.5,
          delay: 0.05 * index,
          x: 1,
          y: 1,
          z: 1,
          ease: "circ.out",
        }),
        "bar"
      );
    });

    // areaPoint动画 - 在地块动画完成后出现
    this.pointEventElement.map((areaPoint, index) => {
      tl.add(
        gsap.to(areaPoint.material, {
          duration: 0.5,
          delay: 0.05 * index,
          opacity: 1,
          ease: "circ.out",
        }),
        "bar"
      );
    });
  }
  // 初始化环境灯光
  initEnvironment() {
    let sun = new AmbientLight(0xffffff, 5); // 提升环境光强度
    this.scene.add(sun);
    // 方向光
    let directionalLight = new DirectionalLight(0xffffff, 5); // 提升方向光强度
    directionalLight.position.set(-30, 6, -8);
    directionalLight.castShadow = true;
    directionalLight.shadow.radius = 20;
    directionalLight.shadow.mapSize.width = 1024;
    directionalLight.shadow.mapSize.height = 1024;
    this.scene.add(directionalLight);

    // this.createPointLight({
    //   color: "#1d5e5e",
    //   intensity: 800,
    //   distance: 10000,
    //   x: -9,
    //   y: 3,
    //   z: -3,
    // });
    // this.createPointLight({
    //   color: "#1d5e5e",
    //   intensity: 200,
    //   distance: 10000,
    //   x: 0,
    //   y: 2,
    //   z: 5,
    // });
  }

  createPointLight(pointParams) {
    // 点光源
    const pointLight = new PointLight(
      0x1d5e5e,
      pointParams.intensity,
      pointParams.distance,
      1
    );
    pointLight.position.set(pointParams.x, pointParams.y, pointParams.z);
    this.scene.add(pointLight);
  }
  // 设置debug ,stats,axes
  initSetting() {
    this.renderer.resize();
  }
  // 模型渲染
  createModel() {
    let mapGroup = new Group();
    mapGroup.name = "chinaMapGroup";
    let focusMapGroup = new Group();
    this.focusMapGroup = focusMapGroup;
    // 地图
    let { province } = this.createProvince();
    this.provinceMesh = province;
    province.setParent(focusMapGroup);
    focusMapGroup.position.set(0, 0, -5);
    focusMapGroup.scale.set(1, 1, 0);

    mapGroup.add(focusMapGroup);
    mapGroup.position.set(0, 0.2, 0);
    // this.setScale(province);
    this.mainSceneGroup.add(mapGroup);
  }

  calculateScale(parentBoxSize, boxSize) {
    let xScale = parentBoxSize[0] / boxSize[0];
    let yScale = parentBoxSize[1] / boxSize[1];
    let scale = Math.min(xScale, yScale);

    return scale;
  }
  getMapData() {
    let mapJsonData = {};
    let detailMapJsonData = {};
    const xhr = new XMLHttpRequest();
    xhr.open("GET", `/api/geo/areas_v3/bound/${this.adcode}.json`, false); // 第三个参数设为false实现同步
    xhr.onreadystatechange = function () {
      if (xhr.readyState === 4) {
        if (xhr.status === 200) {
          mapJsonData = xhr.response;
        } else {
          error = new Error(`HTTP error! status: ${xhr.status}`);
        }
      }
    };
    xhr.send();
    this.mapJsonData = mapJsonData;
    let mapData = JSON.parse(mapJsonData);
    this.mainProvinceName = mapData.features[0].properties.name;
    console.log("mapData", mapData);
    emitter.$emit("getMapDataEnd", mapData);
    let { childrenNum } = mapData.features[0].properties;
    if (childrenNum && childrenNum > 0) {
      xhr.open(
        "GET",
        `/api/geo/areas_v3/bound/${this.adcode}_full.json`,
        false
      ); // 第三个参数设为false实现同步

      xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
          if (xhr.status === 200) {
            detailMapJsonData = xhr.response;
          } else {
            error = new Error(`HTTP error! status: ${xhr.status}`);
          }
        }
      };

      xhr.send();
      this.detailMapJsonData = detailMapJsonData;
      console.log(
        "detailMapJsonDatadetailMapJsonData",
        JSON.parse(detailMapJsonData)
      );
      return detailMapJsonData;
    }
  }
  // 创建省份
  createProvince() {
    let mapDetailJsonData = this.getMapData();
    // 默认是全国地图
    // let mapJsonData = this.assets.instance.getResource("china");
    // let mapData = JSON.parse(this.mapJsonData);
    // let provinceCenterPointArray = mapData.features[0].properties.centroid;
    this.pointCenter = [108.55, 34.32];
    let topNormal = this.assets.instance.getResource("topNormal");
    topNormal.wrapS = topNormal.wrapT = RepeatWrapping;
    this.provinceLineMaterial = new LineBasicMaterial({
      color: 0xffffff,
      opacity: 0,
      transparent: true,
      fog: false,
    });
    let [topMaterial, sideMaterial] = this.createProvinceMaterial();
    let faceMaterial = new MeshStandardMaterial({
      color: 0xffffff,
      transparent: true,
      opacity: 0.5,
      fog: false,
    });
    this.defaultMaterial = faceMaterial;
    this.defaultLightMaterial = this.defaultMaterial.clone();
    this.defaultLightMaterial.color = new Color("rgba(115,208,255,1)");
    this.defaultLightMaterial.opacity = 0.8;
    this.focusMapTopMaterial = topMaterial;
    this.focusMapSideMaterial = sideMaterial;
    let province = new ExtrudeMap(this, {
      center: this.pointCenter,
      position: new Vector3(0, 0, 0.06),
      data: mapDetailJsonData,
      depth: this.depth,
      topFaceMaterial: topMaterial,
      sideMaterial: sideMaterial,
      lineMaterial: this.provinceLineMaterial,
      renderOrder: 9,
    });
    this.time.on("tick", () => {
      sideMaterial.map.offset.y += 0.002;
    });
    let { boxSize, box3 } = getBoundBox(province.mapGroup);
    this.eventElement = [];
    province.mapGroup.children.map((group, index) => {
      group.children.map((mesh) => {
        if (mesh.type === "Mesh") {
          this.eventElement.push(mesh);
          this.calcUv2(
            mesh.geometry,
            boxSize.x,
            boxSize.y,
            box3.min.x,
            box3.min.y
          );
        }
      });
    });
    return {
      province,
    };
  }
  setScale(map) {
    let parentBoxSize = [129.00074005126953, (126.23402404785156 * 3) / 4];
    let boundBox = getBoundBox(map.mapGroup);
    let scale = this.calculateScale(parentBoxSize, [
      boundBox.boxSize.x,
      boundBox.boxSize.y,
    ]);
    // // 子地图缩放到主地图大小
    map.mapGroup.scale.set(scale, scale, 1);
    let boundBox1 = getBoundBox(map.mapGroup);
    // // 放大后，中心坐标有偏移，偏移了多少，就反向移动多少
    map.mapGroup.position.x = -boundBox1.center.x;
    map.mapGroup.position.y = -boundBox1.center.y;
    this.scale = scale;
    this.boundBox = boundBox1;
  }
  // 添加事件
  addEvent() {
    let objectsHover = [];

    const reset = (mesh) => {
      gsap.to(mesh.scale, {
        duration: 0.3,
        z: 1,
        onComplete: () => {
          mesh.traverse((obj) => {
            if (obj.isMesh) {
              obj.material[0].emissive.setHex(
                mesh.userData.materialEmissiveHex
              );
              obj.material[0].emissiveIntensity = 1;
              obj.renderOrder = 9;
            }
          });
        },
      });
      this.setBarMove(mesh.userData.adcode, "down");
      this.setGQMove(mesh.userData.adcode, "down");
      this.setLabelMove(mesh.userData.adcode, "down");
      this.setScatterMove(mesh.userData.adcode, "down");
    };
    const move = (mesh) => {
      mesh.traverse((obj) => {
        if (obj.isMesh) {
          obj.material[0].emissive.setHex(0x337ecc);
          obj.material[0].emissiveIntensity = 2.5;
          obj.renderOrder = 21;
        }
      });
      gsap.to(mesh.scale, {
        duration: 0.3,
        z: 1.5,
      });
      // this.setBarMove(mesh.userData.adcode);
      // this.setGQMove(mesh.userData.adcode);
      // this.setLabelMove(mesh.userData.adcode);
      // this.setScatterMove(mesh.userData.adcode);
    };

    // 循环添加事件
    this.eventElement.map((mesh) => {
      this.interactionManager.add(mesh);
      mesh.addEventListener("mousedown", (event) => {
        if (this.clicked || !this.mainSceneGroup.visible) return false;
        this.clicked = true;
        let userData = event.target.parent.userData;
        emitter.$emit("loadChildMap", userData);
        this.history.push(userData);
        this.loadChildMap(userData);
      });
      mesh.addEventListener("mouseup", (ev) => {
        this.clicked = false;
      });
      mesh.addEventListener("mouseover", (event) => {
        if (!objectsHover.includes(event.target.parent)) {
          objectsHover.push(event.target.parent);
        }

        if (this.mainSceneGroup.visible) {
          document.body.style.cursor = "pointer";
        }
        // 放大对应地块的label
        const adcode = event.target.parent.userData.adcode;
        this.allProvinceNameLabel.forEach((label) => {
          if (label.userData.adcode === adcode) {
            // 记录原始scale，便于后续还原
            if (!label.userData.originalScale) {
              label.userData.originalScale = {
                x: label.scale.x,
                y: label.scale.y,
                z: label.scale.z,
              };
            }
            gsap.to(label.scale, {
              x: label.userData.originalScale.x * 1.5,
              y: label.userData.originalScale.y * 1.5,
              z: label.userData.originalScale.z * 1.5,
              duration: 0.3,
            });
          }
        });
        move(event.target.parent);
      });
      mesh.addEventListener("mouseout", (event) => {
        objectsHover = objectsHover.filter(
          (n) => n.userData.name !== event.target.parent.userData.name
        );
        if (objectsHover.length > 0) {
          const mesh = objectsHover[objectsHover.length - 1];
        }
        const adcode = event.target.parent.userData.adcode;
        this.allProvinceNameLabel.forEach(label => {
          if (label.userData.adcode === adcode) {
            // 还原到原始scale
            const ori = label.userData.originalScale || {x: this.scale, y: this.scale, z: this.scale};
            gsap.to(label.scale, {
              x: ori.x,
              y: ori.y,
              z: ori.z,
              duration: 0.3,
            });
          }
        });
        reset(event.target.parent);
        document.body.style.cursor = "default";
      });
    });
  }

  /**
   * 设置柱状图移动
   * @param {*} name
   * @param {*} type up-上移  down-下移
   */
  setBarMove(adcode, type = "up") {
    this.allBar.map((barGroup) => {
      if (barGroup.userData.adcode === adcode) {
        gsap.to(barGroup.position, {
          duration: 0.3,
          z:
            type === "up"
              ? barGroup.userData.position[2] + this.depth / 2 + 0.3
              : barGroup.userData.position[2],
        });
      }
    });
  }
  /**
   * 设置光圈移动
   * @param {*} name
   * @param {*} type up-上移  down-下移
   */
  setGQMove(adcode, type = "up") {
    this.allGuangquan.map((group) => {
      if (group.userData.adcode === adcode) {
        gsap.to(group.position, {
          duration: 0.3,
          z:
            type === "up"
              ? group.userData.position[2] + this.depth / 2 + 0.3
              : group.userData.position[2],
        });
      }
    });
    if (this.flyLineFocusGroup.userData.adcode === adcode) {
      console.log(this.flyLineFocusGroup.userData.adcode);
      gsap.to(this.flyLineFocusGroup.position, {
        duration: 0.3,
        y:
          type === "up"
            ? this.flyLineFocusGroup.userData.position[1] + this.depth / 2 + 0.3
            : this.flyLineFocusGroup.userData.position[1],
      });
    }
  }
  // 设置标签移动
  setLabelMove(adcode, type = "up") {
    [...this.allProvinceLabel, ...this.allProvinceNameLabel].map((label) => {
      if (label.userData.adcode === adcode) {
        gsap.to(label.position, {
          duration: 0.3,
          z:
            type === "up"
              ? label.userData.position[2] + this.depth / 2 + 0.3
              : label.userData.position[2],
        });
      }
    });
  }
  /**
   * 设置散点图移动
   * @param {*} adcode
   * @param {*} type
   */
  setScatterMove(adcode, type = "up") {
    this.scatterGroup.children.map((sprite) => {
      if (sprite.userData.adcode === adcode) {
        gsap.to(sprite.position, {
          duration: 0.3,
          z:
            type === "up"
              ? sprite.userData.position[2] + this.depth / 2 + 0.3
              : sprite.userData.position[2],
        });
      }
    });
  }

  // 加载子地图
  loadChildMap(userData) {
    this.toastLoading.show();
    this.getChildMapData(userData, ({ fullData, normalData }) => {
      console.log(fullData);
      console.log(normalData);

      this.returnBtn.style.display = "block";
      this.childMap && this.childMap.destroy();
      this.childMap = new ChildMap(this, {
        adcode: userData.adcode,
        center: userData.center,
        centroid: userData.centroid,
        childrenNum: userData.childrenNum,
        mapData: fullData,
        storkeMapData: normalData,
        time: this.time,
        parentBoxSize: [129.00074005126953, (126.23402404785156 * 3) / 4],
      });
      this.childSceneGroup.add(this.childMap.instance);
      this.setMainMapVisible(false);
      this.toastLoading.hide();
      this.camera.controls.reset();
      this.currentScene = "childScene";
      this.config.setEnable(false);
      this.allInfoLabel = [];
      // 清空主地图的allProvinceLabel并彻底移除
      this.allProvinceNameLabel.forEach((label) => {
        let elements = label.element.querySelector(
          ".provinces-name-label-wrap"
        );
        if (elements) {
          elements.style.display = "none";
        }
        // label.hide();
      });
      // 如果有专门的Group
      if (
        this.provinceNameGroup &&
        typeof this.provinceNameGroup.clear === "function"
      ) {
        this.provinceNameGroup.clear();
      }
    });
  }

  getChildMapData(userData, callback) {
    const baseUrl = `/api/geo/areas_v3/bound/${userData.adcode}`;
    const fullUrl = `${baseUrl}_full.json`;
    const normalUrl = `${baseUrl}.json`;

    // 根据 childrenNum 决定请求策略
    if (userData.childrenNum === 0) {
      // 当 childrenNum 为 0 时，只请求普通数据
      fetch(normalUrl, {
        headers: {
          "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
          Referer: window.location.origin,
        },
      })
        .then((res) => res.text())
        .then((normalData) => {
          callback && callback({ fullData: null, normalData });
        })
        .catch((err) => {
          console.error("获取普通地图数据失败:", err);
          callback && callback(null, err);
        });
    } else {
      // 当 childrenNum 不为 0 时，请求两种数据
      const fetchFullData = fetch(fullUrl, {
        headers: {
          "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
          Referer: window.location.origin,
        },
      })
        .then((res) => res.text())
        .catch((err) => {
          console.error("获取完整地图数据失败:", err);
          return null;
        });

      const fetchNormalData = fetch(normalUrl, {
        headers: {
          "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
          Referer: window.location.origin,
        },
      })
        .then((res) => res.text())
        .catch((err) => {
          console.error("获取普通地图数据失败:", err);
          return null;
        });

      // 并行处理两个请求
      Promise.all([fetchFullData, fetchNormalData])
        .then(([fullData, normalData]) => {
          callback && callback({ fullData, normalData });
        })
        .catch((err) => {
          console.error("获取地图数据失败:", err);
          callback && callback(null, err);
        });
    }
  }
  // 隐藏显示主地图及标签
  setMainMapVisible(bool) {
    this.scene.getObjectByName("chinaMapGroup").visible = bool;
    this.mainSceneGroup.visible = bool;

    if (bool === false) {
      this.setLabelVisible("provinceNameGroup", bool);
      this.setLabelVisible("labelGroup", bool);
      this.setLabelVisible("badgeGroup", bool);
    }
  }
  // 返回上一级
  goBack() {
    this.history.undo();
    if (!this.history.getIndex()) {
      this.currentScene = "mainScene";
      this.returnBtn.style.display = "none";

      this.childMap && this.childMap.destroy();
      this.childMap = null;
      emitter.$emit("loadChildMap", { name: this.mainProvinceName });

      this.setMainMapVisible(true);
      this.setLabelVisible("labelGroup", true);
      this.setLabelVisible("provinceNameGroup", true);
      let tl = gsap.timeline();
      this.allProvinceNameLabel.map((item, index) => {
        let element = item.element.querySelector(".provinces-name-label-wrap");
        element.style.display = "";
        // item.show()
        tl.add(
          gsap.to(element, {
            duration: 0.5,
            delay: 0.05 * index,
            translateY: 0,
            opacity: 1,
            ease: "circ.out",
          }),
          "bar"
        );
      });
    } else {
      let userData = this.history.present;
      emitter.$emit("loadChildMap", userData);
      this.loadChildMap(userData);
    }

    this.camera.controls.reset();
  }

  calcUv2(geometry, width, height, minX, minY) {
    const positionAttribute = geometry.attributes.position;
    const uvAttribute = geometry.attributes.uv;

    const count = geometry.groups[0].count;
    for (let i = 0; i < count; i++) {
      const x = positionAttribute.getX(i);
      const y = positionAttribute.getY(i);

      const u = (x - minX) / width;
      const v = (y - minY) / height;

      uvAttribute.setXY(i, u, v);
    }

    uvAttribute.needsUpdate = true;
    geometry.computeVertexNormals();
  }

  createProvinceMaterial() {
    let topMaterial = new MeshLambertMaterial({
      color: 0xffffff, // 基础色白色
      transparent: true,
      opacity: 0.4, // 交给shader控制
      fog: false,
      side: DoubleSide,
    });
    topMaterial.onBeforeCompile = (shader) => {
      shader.uniforms = {
        ...shader.uniforms,
        uColor1: { value: new Color(0x7ed6fb) }, // 浅蓝
        uColor2: { value: new Color(0x27408b) }, // 深蓝
      };
      shader.vertexShader = shader.vertexShader.replace(
        "void main() {",
        `
        attribute float alpha;
        varying vec3 vPosition;
        varying float vAlpha;
        void main() {
          vAlpha = alpha;
          vPosition = position;
      `
      );
      shader.fragmentShader = shader.fragmentShader.replace(
        "void main() {",
        `
        varying vec3 vPosition;
        varying float vAlpha;
        uniform vec3 uColor1;
        uniform vec3 uColor2;
        void main() {
      `
      );
      shader.fragmentShader = shader.fragmentShader.replace(
        "#include <opaque_fragment>",
        /* glsl */ `
      #ifdef OPAQUE
      diffuseColor.a = 1.0;
      #endif
            #ifdef USE_TRANSMISSION
      diffuseColor.a *= transmissionAlpha + 0.1;
      #endif
      vec3 gradient = mix(uColor1, uColor2, 0.1);
      float highlight = length(emissive); // 0~1
      vec3 finalColor = mix(gradient, emissive, highlight);
      gl_FragColor = vec4(finalColor, diffuseColor.a);
      `
      );
    };
    let sideMap = this.assets.instance.getResource("side");
    sideMap.wrapS = RepeatWrapping;
    sideMap.wrapT = RepeatWrapping;
    sideMap.repeat.set(1, 0.2);
    sideMap.offset.y += 0.065;
    let sideMaterial = new MeshStandardMaterial({
      color: 0xffffff,
      map: sideMap,
      fog: false,
      transparent: true,
      opacity: 0,
      side: DoubleSide,
    });
    sideMaterial.onBeforeCompile = (shader) => {
      shader.uniforms = {
        ...shader.uniforms,
        uColor1: { value: new Color(0x2a6e92) },
        uColor2: { value: new Color(0x2a6e92) },
      };
      shader.vertexShader = shader.vertexShader.replace(
        "void main() {",
        `
        attribute float alpha;
        varying vec3 vPosition;
        varying float vAlpha;
        void main() {
          vAlpha = alpha;
          vPosition = position;
      `
      );
      shader.fragmentShader = shader.fragmentShader.replace(
        "void main() {",
        `
        varying vec3 vPosition;
        varying float vAlpha;
        uniform vec3 uColor1;
        uniform vec3 uColor2;
        void main() {
      `
      );
      shader.fragmentShader = shader.fragmentShader.replace(
        "#include <opaque_fragment>",
        /* glsl */ `
      #ifdef OPAQUE
      diffuseColor.a = 1.0;
      #endif
            #ifdef USE_TRANSMISSION
      diffuseColor.a *= transmissionAlpha + 0.1;
      #endif
      vec3 gradient = mix(uColor1, uColor2, vPosition.z/1.2);
      outgoingLight = outgoingLight*gradient;
      gl_FragColor = vec4( outgoingLight, diffuseColor.a  );
      `
      );
    };
    return [topMaterial, sideMaterial];
  }
  addPointLabel(data) {
    // 贴图
    const texture = this.assets.instance.getResource("point");
    const material = new SpriteMaterial({
      map: texture,
      color: 0xffffff,
      transparent: true,
      depthTest: false,
      fog: false,
    });
    this.pointDefaultMaterial = material;
    this.pointHoverMaterial = material.clone();
    this.pointHoverMaterial.color = new Color(0xff0000);
    const sprite = new Sprite(material);
    sprite.renderOrder = 23;
    this.allPointLabel = [];
    this.allInfoLabel = [];
    this.pointEventElement = [];
    this.areaPointGroup.clear();
    this.infoLabelGroup.clear();
    this.areaLabelGroup.clear();
    let _this = this;
    data.map((item, index) => {
      let [x, y] = this.geoProjection(item.centroid);
      // 应用缩放和偏移
      let px = x * (this.scale || 1) - (this.boundBox?.center.x || 0);
      let py = -y * (this.scale || 1) - (this.boundBox?.center.y || 0);
      let infoLabel = _this.infoLabel(item, index, new Vector3(px, py, 20));
      this.allInfoLabel.push(infoLabel);

      // 根据 value 字段设置不同颜色
      let color = 0xffffff; // 默认白色
      if (item.value >= 7) {
        color = 0xf56c6c; // 红色
      } else if (item.value >= 5) {
        color = 0xe6a23c; // 黄色
      } else {
        color = 0xb3e19d; // 绿色
      }

      // 为每个点单独创建 material
      let pointMaterial = new SpriteMaterial({
        map: texture,
        color: color,
        transparent: true,
        depthTest: false,
        fog: false,
      });

      let areaPoint = new Sprite(pointMaterial);
      // areaPoint.material = material.clone();
      areaPoint.position.set(px, py, 0);
      areaPoint.scale.set(0, 0, 0); // 初始缩放为0
      areaPoint.material.opacity = 0; //
      areaPoint.userData.adcode = item.adcode;
      areaPoint.userData.type = "point";
      areaPoint.userData.name = item.name;
      areaPoint.userData.position = [px, py, 0];
      areaPoint.userData.index = index;
      this.areaPointGroup.add(areaPoint);
      this.pointEventElement.push(areaPoint);

      // 设置渲染顺序
      areaPoint.renderOrder = 99;
      areaPoint.userData.originalMaterial = pointMaterial; // 保存原始材质
      areaPoint.userData.originalColor = pointMaterial.color.clone(); // 保存原始颜色
    });
    // this.setPointLabelScale();
    // this.setInfoLabelScale();
    this.setPointScale();
    this.addPointEvent();
  }
  // 信息标签
  infoLabel(data, index, position) {
    let label3d = this.label3d;
    let label = label3d.create("", "info-point", true);
    label.init(
      ` <div class="info-point-wrap">
      <div class="info-point-wrap-inner">
        <div class="info-point-line">
          <div class="line"></div>
          <div class="line"></div>
          <div class="line"></div>
        </div>
        <div class="info-point-content">
          <div class="content-item"><span class="label">名称</span><span class="value">${data.name}</span></div>
          <div class="content-item"><span class="label">震级</span><span class="value">6.0</span></div>
          <div class="content-item"><span class="label">等级</span><span class="value">良好</span></div>
        </div>
      </div>
    </div>
  `,
      position
    );
    label3d.setLabelStyle(label, 0.06 / (this.scale || 1), "x");
    label.setParent(this.infoLabelGroup);
    label.hide();
    return label;
  }
  // 名称标签缩放
  setPointLabelScale() {
    this.allPointLabel.map((label) => {
      let z = (this.depth + 0.4) / (this.scale || 1);
      label.position.z = z;
      label.userData.position = [
        label.position.x,
        label.position.y,
        label.position.z,
      ];
    });
  }

  // 信息标签缩放
  setInfoLabelScale() {
    this.infoLabelGroup.scale.set(
      this.scale || 1,
      this.scale || 1,
      this.scale || 1
    );
    // 修正：对齐子地图逻辑，设置中心点偏移
    this.infoLabelGroup.position.x = -this.boundBox.center.x;
    this.infoLabelGroup.position.y = -this.boundBox.center.y;
    this.infoLabelGroup.children.map((point) => {
      let z = (this.depth + 10) / (this.scale || 1);
      point.position.z = z;
      point.scale.set(
        0.06 / (this.scale || 1),
        0.06 / (this.scale || 1),
        0.06 / (this.scale || 1)
      );
    });
  }
  // 点缩放
  setPointScale() {
    this.areaPointGroup.scale.set(
      this.scale || 1,
      this.scale || 1,
      this.scale || 1
    );
    this.areaPointGroup.position.x = 0;
    this.areaPointGroup.position.y = 0;
    this.areaPointGroup.children.map((point) => {
      let z = (this.depth + 1.4) / (this.scale || 1);
      point.position.z = z;
      point.userData.position[2] = z;
      point.scale.set(
        5 / (this.scale || 1),
        5 / (this.scale || 1),
        5 / (this.scale || 1)
      );
      point.userData.position = [
        point.position.x,
        point.position.y,
        point.position.z,
      ];
    });
  }
  // 点事件
  addPointEvent() {
    let objectsHover = [];
    this.pointEventElement.map((mesh, idx) => {
      this.interactionManager.add(mesh);
      mesh.addEventListener("mouseup", (ev) => {
        this.clicked = false;
      });
      mesh.addEventListener("mouseover", (event) => {
        if (!objectsHover.includes(event.target)) {
          let userData = event.target.userData;
          this.allInfoLabel.map((label, index) => {
            label.hide();
            if (userData.index === index) {
              label.show();
            }
          });
          objectsHover.push(event.target);
        }
        document.body.style.cursor = "pointer";
        let sprite = event.target;
        sprite.material.color.set(0xff0000); // 高亮色
      });
      mesh.addEventListener("mouseout", (event) => {

        
        this.allInfoLabel.map((label, index) => {
          label.hide();
        });
        objectsHover = objectsHover.filter(
          (n) => n.userData.name !== event.target.userData.name
        );
        if (objectsHover.length > 0) {
          const mesh = objectsHover[objectsHover.length - 1];
        }
        document.body.style.cursor = "default";
        let sprite = event.target;
        // 还原为原始颜色
        sprite.material.color.copy(sprite.userData.originalColor);
      });
    });
  }
  labelNameStyle(data, index, position) {
    let label3d = this.label3d;
    let label = label3d.create("", "provinces-name-label", true);
    label.init(
      `<div class="provinces-name-label-wrap">${data.name}</div>`,
      position
    );
    label3d.setLabelStyle(label, 0.08, "x"); // 先不用 / this.scale
    label.setParent(this.areaLabelGroup);
    label.userData.adcode = data.adcode;
    label.userData.position = [position.x, position.y, position.z];
    return label;
  }

  // 创建柱状图
  createBar() {
    let self = this;
    let detailMapData = JSON.parse(this.detailMapJsonData);
    let data = detailMapData.features
      .filter(
        (item) =>
          item &&
          item.properties &&
          (item.properties.centroid || item.properties.center)
      )
      .map((item) => {
        let { name, center, centroid, adcode } = item.properties;
        return {
          name,
          center,
          centroid,
          adcode,
        };
      });
    const barGroup = new Group();
    this.barGroup = barGroup;
    const factor = 7;
    const height = 4.0 * factor;
    const max = data[0].value;
    this.allBar = [];
    this.allBarMaterial = [];
    this.allGuangquan = [];
    this.allProvinceLabel = [];
    this.allProvinceNameLabel = [];
    this.addPointLabel(testData);

    // 获取缩放和偏移参数
    const scale = this.scale;
    const offsetX = -this.boundBox.center.x;
    const offsetY = -this.boundBox.center.y;

    data.map((item, index) => {
      let geoHeight = height * (item.value / max);
      let material = new MeshBasicMaterial({
        color: 0xffffff,
        transparent: true,
        opacity: 0,
        depthTest: false,
        fog: false,
      });
      new GradientShader(material, {
        uColor1: index < 3 ? 0xfbdf88 : 0x50bbfe,
        uColor2: index < 3 ? 0xfbdf88 : 0x50bbfe,
        size: geoHeight,
        dir: "y",
      });
      const geo = new BoxGeometry(0.05 * factor, 0.05 * factor, geoHeight);
      geo.translate(0, 0, geoHeight / 2);
      const mesh = new Mesh(geo, material);
      mesh.renderOrder = 22;
      let areaBar = mesh;
      let [x, y] = this.geoProjection(item.centroid || item.center);
      areaBar.position.set(x, -y, this.depth + 0.46);
      areaBar.scale.set(1, 1, 0);
      areaBar.userData.name = item.name;
      areaBar.userData.adcode = item.adcode;
      areaBar.userData.position = [x, -y, this.depth + 0.46];
      let guangQuan = this.createQuan();
      guangQuan.position.set(x, -y, this.depth + 0.46);
      guangQuan.userData.name = item.name;
      guangQuan.userData.adcode = item.adcode;
      guangQuan.userData.position = [x, -y, this.depth + 0.46];
      // 柱状图和光圈等
      barGroup.add(areaBar);
      // label坐标应用缩放和偏移
      let lx = x * scale + offsetX;
      let ly = -y * scale + offsetY;
      let nameLabel = this.labelNameStyle(
        item,
        index,
        new Vector3(lx, ly, this.depth + 0.4)
      );
      this.allProvinceNameLabel.push(nameLabel);
    });
  }

  setNameScale() {
    this.areaLabelGroup.scale.set(this.scale, this.scale, this.scale);
    this.areaLabelGroup.position.x = -this.boundBox.center.x;
    this.areaLabelGroup.position.y = -this.boundBox.center.y;
    this.allProvinceNameLabel.map((label) => {
      let z = (1 + 0.4) / this.scale;
      label.position.z = z;
      // 不做y偏移
      label.userData.position = [
        label.position.x,
        label.position.y,
        label.position.z,
      ];
    });
  }
  createHUIGUANG(h, color) {
    let geometry = new PlaneGeometry(1.5, h);
    geometry.translate(0, h / 2, 0);
    const texture = this.assets.instance.getResource("huiguang");
    texture.colorSpace = SRGBColorSpace;
    texture.wrapS = RepeatWrapping;
    texture.wrapT = RepeatWrapping;
    let material = new MeshBasicMaterial({
      color: color,
      map: texture,
      transparent: true,
      opacity: 0.4,
      depthWrite: false,

      side: DoubleSide,
      blending: AdditiveBlending,
    });
    let mesh = new Mesh(geometry, material);
    mesh.renderOrder = 23;
    mesh.rotateX(Math.PI / 2);
    let mesh2 = mesh.clone();
    let mesh3 = mesh.clone();
    mesh2.rotateY((Math.PI / 180) * 60);
    mesh3.rotateY((Math.PI / 180) * 120);
    return [mesh, mesh2, mesh3];
  }
  createQuan() {
    const guangquan1 = this.assets.instance.getResource("guangquan1");
    const guangquan2 = this.assets.instance.getResource("guangquan2");
    let geometry = new PlaneGeometry(2, 2);

    let material1 = new MeshBasicMaterial({
      color: 0xffffff,
      map: guangquan1,
      alphaMap: guangquan1,
      opacity: 1,
      transparent: true,
      depthTest: false,
      fog: false,
      blending: AdditiveBlending,
    });
    let material2 = new MeshBasicMaterial({
      color: 0xffffff,
      map: guangquan2,
      alphaMap: guangquan2,
      opacity: 1,
      transparent: true,
      depthTest: false,
      fog: false,
      blending: AdditiveBlending,
    });
    let mesh1 = new Mesh(geometry, material1);
    let mesh2 = new Mesh(geometry, material2);
    mesh1.renderOrder = 24;
    mesh2.renderOrder = 24;

    mesh2.position.z -= 0.001;
    mesh1.scale.set(0, 0, 0);
    mesh2.scale.set(0, 0, 0);
    this.quanGroup = new Group();
    this.quanGroup.add(mesh1, mesh2);
    this.time.on("tick", (delta) => {
      mesh1.rotation.z += delta * 2;
    });

    return this.quanGroup;
  }
  /**
   * 设置css3d标签的隐藏显示
   * @param {*} labelGroup
   * @param {*} bool
   */
  setLabelVisible(labelGroup = "labelGroup", bool) {
    this[labelGroup].visible = bool;
    this[labelGroup].children.map((label) => {
      bool ? label.show() : label.hide();
    });
  }

  createFloor() {
    let geometry = new PlaneGeometry(200, 200);
    const texture = this.assets.instance.getResource("gaoguang1");
    texture.colorSpace = SRGBColorSpace;
    texture.wrapS = RepeatWrapping;
    texture.wrapT = RepeatWrapping;
    texture.repeat.set(1, 1);
    let material = new MeshBasicMaterial({
      map: texture,
      opacity: 1,
      transparent: true,
      blending: AdditiveBlending,
    });
    let mesh = new Mesh(geometry, material);
    mesh.rotateX(-Math.PI / 2);
    mesh.position.set(0, 0.05, 0);
    this.scene.add(mesh);

    const quanTexture = this.assets.instance.getResource("quan");

    let quan = new Mesh(
      new PlaneGeometry(250, 250),
      new MeshBasicMaterial({
        map: quanTexture,
        opacity: 1,
        transparent: true,
        blending: AdditiveBlending,
        depthTest: false,
      })
    );
    quan.rotateX(-Math.PI / 2);
    quan.position.set(0, this.depth + 2.05, 0);
    this.quan = quan;
    this.scene.add(quan);
  }

  createGridRipple() {
    let geometry = new PlaneGeometry(300, 300);
    const texture = this.assets.instance.getResource("grid");
    const alphaMap = this.assets.instance.getResource("gridBlack");
    texture.wrapS =
      texture.wrapT =
      alphaMap.wrapS =
      alphaMap.wrapT =
        RepeatWrapping;
    texture.repeat.set(40, 40);
    alphaMap.repeat.set(40, 40);
    let material = new MeshBasicMaterial({
      map: texture,
      color: 0xffffff,
      transparent: true,
      opacity: 0.8,
      alphaMap: alphaMap,
      blending: AdditiveBlending,
    });

    let mesh = new Mesh(geometry, material);
    mesh.rotateX(-Math.PI / 2);
    let [x, y] = this.geoProjection(this.pointCenter);
    mesh.position.set(x, -y, 0.01);
    const mesh2 = mesh.clone();
    mesh2.material = material.clone();
    mesh2.material.opacity = 1;
    this.scene.add(mesh, mesh2);
    new DiffuseShader({
      material,
      time: this.time,
      size: 300,
      diffuseColor: 0x079fe6,
      diffuseSpeed: 30,
      diffuseWidth: 20,
      diffuseDir: 2.0,
    });
  }
  createMirror() {
    const geometry = new PlaneGeometry(200, 200);
    const groundMirror = new Reflector(geometry, {
      clipBias: 0.003,
      textureWidth: this.sizes.width,
      textureHeight: this.sizes.height,
      color: 0xb5b5b5,
      multisample: 1,
    });
    groundMirror.material.transparent = true;
    groundMirror.material.opacity = 0.2;
    groundMirror.position.y = -0.01;
    groundMirror.rotateX(-Math.PI / 2);
    this.groundMirror = groundMirror;
    this.groundMirror.visible = false;
    this.scene.add(groundMirror);
  }

  createRotateBorder() {
    //
    let max = 100;
    let rotationBorder1 = this.assets.instance.getResource("rotationBorder1");
    let rotationBorder2 = this.assets.instance.getResource("rotationBorder2");
    let plane01 = new Plane(this, {
      width: max * 1.178,
      needRotate: true,
      rotateSpeed: 0.001,
      material: new MeshBasicMaterial({
        map: rotationBorder1,
        color: 0x48afff,
        transparent: true,
        opacity: 0.2,
        depthWrite: false,
        blending: AdditiveBlending,
      }),
      position: new Vector3(0, 0.07, 0),
    });
    plane01.instance.renderOrder = 6;
    plane01.instance.scale.set(0, 0, 0);
    plane01.setParent(this.scene);
    //
    let plane02 = new Plane(this, {
      width: max * 1.116,
      needRotate: true,
      rotateSpeed: -0.004,
      material: new MeshBasicMaterial({
        map: rotationBorder2,
        color: 0x48afff,
        transparent: true,
        opacity: 0.4,
        depthWrite: false,
        blending: AdditiveBlending,
      }),
      position: new Vector3(0, 0.06, 0),
    });
    plane02.instance.renderOrder = 6;
    plane02.instance.scale.set(0, 0, 0);
    plane02.setParent(this.scene);
    this.rotateBorder1 = plane01.instance;
    this.rotateBorder2 = plane02.instance;
  }

  // 创建粒子
  createParticles() {
    this.particles = new Particles(this, {
      num: 10, // 粒子数量
      range: 200, // 范围
      dir: "up",
      speed: 0.1,
      material: new PointsMaterial({
        map: Particles.createTexture(),
        size: 10,
        color: 0x00eeee,
        transparent: true,
        opacity: 0.3,
        depthTest: false,
        depthWrite: false,
        vertexColors: true,
        blending: AdditiveBlending,
        sizeAttenuation: true,
      }),
    });
    this.particles.instance.position.set(0, 0, 0);
    this.particles.instance.rotation.x = -Math.PI / 2;
    this.particles.setParent(this.scene);
    // 停用,隐藏
    this.particles.enable = false;
    this.particles.instance.visible = false;
  }

  // 创建散点图
  createScatter() {
    this.scatterGroup = new Group();
    this.scatterGroup.visible = false;

    this.mainSceneGroup.add(this.scatterGroup);
    // 贴图
    const texture = this.assets.instance.getResource("arrow");
    const material = new SpriteMaterial({
      map: texture,
      color: 0xffff00,
      transparent: true,
      depthTest: false,
    });

    let scatterAllData = sortByValue(scatterData);
    let max = scatterAllData[0].value;
    scatterAllData.map((data) => {
      const sprite = new Sprite(material);
      sprite.renderOrder = 23;
      let scale = 2 + (data.value / max) * 1;
      sprite.scale.set(scale, scale, scale);
      let [x, y] = this.geoProjection([data.lng, data.lat]);
      sprite.position.set(x, -y, this.depth + 0.41);
      sprite.userData.adcode = data.adcode;
      sprite.userData.position = [x, -y, this.depth + 0.41];
      this.scatterGroup.add(sprite);
    });
  }
  // 创建标牌
  createBadgeLabel() {
    const self = this;
    self.badgeGroup.visible = false;
    badgesData.map((data) => {
      const [x, y] = this.geoProjection(data.geometry.coordinates);
      labelNameStyle(data, new Vector3(x, -y, this.depth + 0.92));
    });
    function labelNameStyle(data, position) {
      let label = self.label3d.create("", "badges-label", true);
      label.init(
        `<div class="badges-label-wrap">
        平均工资：<span>${data.value}元</span>
        <img class="icon" src="${labelArrow}" alt="" />
      </div>`,
        position
      );
      self.label3d.setLabelStyle(label, 0.1, "x");
      label.setParent(self.badgeGroup);
      label.hide();
      label.userData.adcode = data.adcode;
      label.userData.position = [position.x, position.y, position.z];
      return label;
    }
  }
  // 创建飞线
  createFlyLine() {
    // 贴图
    const texture = this.assets.instance.getResource("flyLine");
    texture.wrapS = texture.wrapT = RepeatWrapping;
    texture.generateMipmaps = false;
    texture.magFilter = NearestFilter;
    texture.repeat.set(0.5, 1);
    // 飞线
    let flyLine = new FlyLine(this, {
      centerPoint: this.flyLineCenter,
      data: provincesData,
      texture: texture,
      material: new MeshBasicMaterial({
        map: texture,
        alphaMap: texture,
        color: 0xfbdf88,
        transparent: true,
        fog: false,
        depthTest: false,
        blending: AdditiveBlending,
      }),
    });
    flyLine.setParent(this.mainSceneGroup);
    flyLine.visible = false;
    flyLine.instance.position.z = this.depth + 0.4;

    this.flyLineGroup = flyLine;

    this.createFlyLineFocus();
  }
  createFlyLineFocus() {
    this.flyLineFocusGroup = new Group();
    this.flyLineFocusGroup.visible = false;

    let [x, y] = this.geoProjection(this.flyLineCenter);
    this.flyLineFocusGroup.position.set(x, -y, this.depth + 0.47);
    this.flyLineFocusGroup.userData.name = "北京市"; // 设置光圈的名字
    this.flyLineFocusGroup.userData.adcode = 110000; //设置光圈的adcode
    this.flyLineFocusGroup.userData.position = [x, -y, this.depth + 0.47]; //设置光圈的位置
    this.mainSceneGroup.add(this.flyLineFocusGroup);
    const flyLineFocus = this.assets.instance.getResource("guangquan1");
    const geometry = new PlaneGeometry(5, 5);
    const material = new MeshBasicMaterial({
      color: 0xfbdf88,
      map: flyLineFocus,
      alphaMap: flyLineFocus,
      transparent: true,
      fog: false,
      depthTest: false,
      blending: AdditiveBlending,
    });
    const mesh = new Mesh(geometry, material);
    mesh.renderOrder = 30;
    mesh.scale.set(0, 0, 0);
    const mesh2 = mesh.clone();
    mesh2.material = material.clone();
    this.flyLineFocusGroup.add(mesh, mesh2);
    gsap.to(mesh.material, {
      opacity: 0,
      repeat: -1,
      yoyo: false,
      duration: 1,
    });
    gsap.to(mesh.scale, {
      x: 2,
      y: 2,
      z: 2,
      repeat: -1,
      yoyo: false,
      duration: 1,
    });
    gsap.to(mesh2.material, {
      delay: 0.5,
      opacity: 0,
      repeat: -1,
      yoyo: false,
      duration: 1,
    });
    gsap.to(mesh2.scale, {
      delay: 0.5,
      x: 2,
      y: 2,
      z: 2,
      repeat: -1,
      yoyo: false,
      duration: 1,
    });
  }
  // 创建路径动画
  createPathAnimate() {
    // 贴图
    const texture = this.assets.instance.getResource("pathLine");
    texture.wrapS = texture.wrapT = RepeatWrapping;
    texture.repeat.set(8, 1);
    // 路径
    let transportPath = this.assets.instance.getResource("transportPath");
    transportPath = JSON.parse(transportPath);
    for (let i = 0; i < transportPath.features.length; i++) {
      const element = transportPath.features[i];
      element.geometry.coordinates = [[element.geometry.coordinates]];
    }
    // 数据
    // 格式 [{geometry: {type: 'LineString', coordinates: [[[x,y]]] }}]
    let data = transportPath.features.map((path) => {
      return {
        geometry: path.geometry,
      };
    });
    let pathLine = new PathLine(this, {
      data: data,
      texture: texture,
      renderOrder: 21,
      speed: 0.5,
      material: new MeshBasicMaterial({
        map: texture,
        color: 0xffffff,
        transparent: true,
        fog: false,
        opacity: 1,
        depthTest: false,
        blending: AdditiveBlending,
      }),
    });
    // 设置父级
    pathLine.setParent(this.mainSceneGroup);
    // 隐藏
    pathLine.visible = false;
    // 位置
    pathLine.instance.position.z = this.depth + 0.42;

    this.pathLineGroup = pathLine;
  }

  // 创建轮廓
  createStorke() {
    // 贴图
    const texture = this.assets.instance.getResource("pathLine2");
    texture.wrapS = texture.wrapT = RepeatWrapping;
    texture.repeat.set(1, 1);
    // 路径
    let mapJsonData = "";
    if (this.adcode === "100000") {
      mapJsonData = this.assets.instance.getResource("chinaStorke");
    } else {
      mapJsonData = this.mapJsonData;
    }

    mapJsonData = JSON.parse(mapJsonData);

    // 数据
    // 格式 [{geometry: {type: '', coordinates: [[[x,y]]] }}]
    let data = mapJsonData.features.map((path) => {
      return {
        geometry: path.geometry,
      };
    });

    let pathLine = new PathLine(this, {
      data: data,
      texture: texture,
      renderOrder: 21,
      speed: 0.2,
      radius: 0.2,
      segments: 256 * 10,
      radialSegments: 4,
      material: new MeshBasicMaterial({
        color: 0x2bc4dc,
        map: texture,
        alphaMap: texture,
        fog: false,
        transparent: true,
        opacity: 1,
        blending: AdditiveBlending,
      }),
    });
    // 设置父级
    pathLine.setParent(this.mainSceneGroup);

    // 位置]
    pathLine.instance.position.z = this.depth + 0.38;
    pathLine.instance.scale.set(this.scale, this.scale, 1);
    pathLine.instance.position.x = -this.boundBox.center.x;
    pathLine.instance.position.y = -this.boundBox.center.y;
  }
  createWatermark() {
    let watermark = this.assets.instance.getResource("watermark");
    watermark.wrapS = RepeatWrapping;
    watermark.wrapT = RepeatWrapping;
    watermark.repeat.set(50, 50);
    watermark.rotation = Math.PI / 5;
    let geometry = new PlaneGeometry(100, 100, 1);
    let material = new MeshBasicMaterial({
      // color: 0xffffff,
      map: watermark,
      // side: DoubleSide,
      transparent: true,
      opacity: 0.15,
    });
    let mesh = new Mesh(geometry, material);
    mesh.position.x -= 10;
    mesh.position.y -= 10;
    mesh.position.z -= 10;
    mesh.renderOrder = 999;
    this.camera.instance.add(mesh);
  }
  // 更新
  update() {
    super.update();
    this.label3d && this.label3d.update();
    this.stats && this.stats.update();
    this.interactionManager && this.interactionManager.update();
  }
  // 销毁
  destroy() {
    super.destroy();
    this.label3d && this.label3d.destroy();
    this.stats && this.stats.dom && document.body.removeChild(this.stats.dom);
    this.groundMirror && this.groundMirror.dispose();
    this.toastLoading && this.toastLoading.destroy();
    this.childMap && this.childMap.destroy();
  }
}
